Graphing Sea Surface Temperature since 1854¶
Imports and Library Dependencies¶
In [34]:
# Imports
import xarray as xr
import numpy as np
import scipy
import matplotlib.pyplot as plt
import matplotlib
import geoviews as gv
import geoviews.feature as gf
import holoviews as hv
from geoviews import opts
from cartopy import crs
gv.extension('bokeh', 'matplotlib')
import datetime
from datetime import date
Pull ERSST Dataset from NOAA¶
In [2]:
# Get ERSST dataset
data_url = 'https://psl.noaa.gov/thredds/dodsC/Datasets/noaa.ersst.v5/sst.mnmean.nc'
sst = xr.open_dataset(data_url).load()
Transform ERSST data with Downsampling and Anomaly Calculation¶
In [18]:
# Downsample sst Data by year
#sst_annual = sst.resample(time = 'AS').mean(dim='time', skipna=True)
sst_annual = sst.groupby('time.year').mean()
In [20]:
# Find Anomaly
# Calculate annual average
ga_sst = sst_annual.median(dim='year', skipna=True)
# Calculate anomaly by subtracting year's average from all indexes
sst_anomaly = sst_annual - ga_sst
Splice Global SST data into North Atlantic Region¶
In [21]:
# convert lon coordinates from 0:360 to -180:180 to ease splicing
sst_anomaly.coords['lon'] = (sst_anomaly.coords['lon'] + 180) % 360 - 180
sst_anomaly = sst_anomaly.sortby(sst_anomaly.lon)
#sst_anomaly # use this line to display data series
In [22]:
# Select North Atlantic Region for anomaly
# Note -- Lat [-90:90] Lon [0:360]
na_sst_anom = sst_anomaly.sel(lon=slice(-99,13), lat=slice(90,0))
na_sst_anom # use this line to display data series
Out[22]:
<xarray.Dataset> Size: 3MB
Dimensions: (lat: 45, year: 171, nbnds: 2, lon: 56)
Coordinates:
* lat (lat) float32 180B 88.0 86.0 84.0 82.0 80.0 ... 6.0 4.0 2.0 0.0
* year (year) int64 1kB 1854 1855 1856 1857 1858 ... 2021 2022 2023 2024
* lon (lon) float32 224B -98.0 -96.0 -94.0 -92.0 ... 6.0 8.0 10.0 12.0
Dimensions without coordinates: nbnds
Data variables:
time_bnds (year, nbnds) float64 3kB 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0
sst (year, lat, lon) float64 3MB 0.0 0.0 0.0 0.0 ... 2.229 2.202 nanIn [23]:
# Transform lon coords back to ranging from 0:360
na_sst_anom.coords['lon'] = (na_sst_anom.coords['lon'] - 180) % 360 + 180
na_sst_anom = na_sst_anom.sortby(na_sst_anom.lon)
Setup for Interactive Plot¶
In [38]:
# UNCOMMENT ONE LINE TO USE DECADAL OR ANNUAL -- DECADAL REDUCES LOAD TIME
na_sst_anom_fin = na_sst_anom.load() # annual
#na_sst_anom_fin = na_sst_anom.resample(time = '10YE').mean() # decadal
# Create dataset
plt_sst = gv.Dataset(na_sst_anom_fin)
# plt_sst = gv.Dataset(na_sst_anom.sel(time=slice('1954-07-31T00:00:00.000000000','2024-07-31T00:00:00.000000000'))) #Load specific time chunck
ensemble = plt_sst.to(gv.Image, ['lon', 'lat'], 'sst', label='North Atlantic Annual Sea Surface Anomaly (1854-2024)')
Interactive Plot generation¶
In [39]:
%%time
# Plot Anomaly
# Dev Note: Takes ~8.5 minutes to load figure w/ yearly anomaly
sst_anom_plt = gv.output(ensemble.opts(clabel='SST Anomaly (C)', cmap='RdBu_r', clim=(-3.5, 3.5), colorbar=True, fig_size=100, backend='matplotlib') * gf.coastline(), backend='matplotlib')